package fx.utils;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Console;
import cn.hutool.core.util.HexUtil;
import com.alibaba.fastjson.JSON;

import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.SecureRandom;

public class DESEncoder {
    //DES算法填充方式
    public static final String ALGORITHM_DES = "DES/ECB/NoPadding";

//    public static void main(String[] args) throws Exception {
//        //项目公解密过程
//        String projectId = "00002345";
//        String encryptedPubKey = "8A53228E9B225225";
//        String userId = "12345678";
//        System.out.println("项目ID(key):" + projectId + " 项目密钥密文(data)：" + encryptedPubKey);
//        String pubKey = DESEncoder.decode(projectId, encryptedPubKey);
//        System.out.println("解密得到项目密钥:" + pubKey);
//        System.out.println("项目密钥(key):" + pubKey + " 用户ID(data)：" + userId);
//        String userKey = DESEncoder.encode(pubKey, userId);
//        System.out.println("加密得到用户密钥:" + userKey);
//        /*******************示例输出结果***********************：
//         项目ID(key):00002345
//         项目密钥密文(data)：8A53228E9B225225
//         解密得到项目密钥:C1A1B0D0A1C2C6D5
//         项目密钥(key):C1A1B0D0A1C2C6D5 用户ID(data)：12345678
//         加密得到用户密钥:274DAF91A273CBA2
//         **********************************************************/
//    }

    /**
     * <desc>
     * DES算法，解密.
     * </desc>
     *
     * @param data 待解密的HEX字符串
     * @param key  解密私钥，HEX字符串，长度不能够小于8位
     * @return 解密后的字符串
     * @throws Exception 异常
     * @author LewisLouis
     * @createDate 2017-11-10
     */
    public static String decode(String key, String data) throws Exception {
        //key的长度不能够小于8位字节
        key = fillString(key, "0", 16);
        byte[] keyBytes = hexStrToBytes(key);
        byte[] dataBytes = hexStrToBytes(data);
        SecureRandom sr = new SecureRandom();
        DESKeySpec dks = new DESKeySpec(keyBytes);
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
        Key secretKey = keyFactory.generateSecret(dks);
        Cipher cipher = Cipher.getInstance(ALGORITHM_DES);
        cipher.init(Cipher.DECRYPT_MODE, secretKey);
        byte[] decryptedBytes = cipher.doFinal(dataBytes);
        return bytesToHexStr(decryptedBytes);
    }


    /**
     * <desc>
     * DES算法，加密.
     * </desc>
     *
     * @param data 待加密的HEX字符串
     * @param key  加密私钥，HEX字符串，长度不能够小于8位
     * @return 加密字符串
     * @author LewisLouis
     * @createDate 2017-11-10
     */
    public static String encode(String key, String data) throws Exception {
        try {
            //key的长度不能够小于8位字节
            key = fillString(key, "0", 16);
            data = fillString(data, "0", 16);
            byte[] keyBytes = hexStrToBytes(key);
            byte[] dataBytes = hexStrToBytes(data);
            DESKeySpec dks = new DESKeySpec(keyBytes);
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
            Key secretKey = keyFactory.generateSecret(dks);
            Cipher cipher = Cipher.getInstance(ALGORITHM_DES);
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
            byte[] encryptedBytes = cipher.doFinal(dataBytes);
            return bytesToHexStr(encryptedBytes);
        } catch (Exception e) {
            throw new Exception(e);
        }
    }

    public static void main(String[] args) throws Exception {
        encode("93EDC46B965D854E", "14981681");
        byte[] bytes = HexUtil.decodeHex("93EDC46B965D854E");
        System.out.println(bytes);
    }


    /**
     * <desc>
     * 自动后补齐字符串
     * </desc>
     *
     * @param str    字符串
     * @param supply 待填充的字符
     * @param length 要求填充后达到的字符串总长度
     * @return 填充后的字符串
     * @author LewisLouis
     * @createDate 2017-11-10
     */
    public static String fillString(String str, String supply, int length) {
        StringBuffer sb = new StringBuffer(str);
        while (sb.length() < length) {
            sb.append(supply);
        }
        return sb.toString();
    }

    /**
     * <desc>
     * 把16进制字符串转换成字节数组.
     * </desc>
     *
     * @param hex 待转换的Hex字符串
     * @return 转换得到的byte数组
     * @author LewisLouis
     * @createDate 2017-11-10
     */
    public static byte[] hexStrToBytes(String hex) {
        int len = (hex.length() / 2);
        byte[] result = new byte[len];
        char[] achar = hex.toCharArray();
        for (int i = 0; i < len; i++) {
            int pos = i * 2;
            result[i] = (byte) (toByte(achar[pos]) << 4 | toByte(achar[pos + 1]));
        }
        return result;
    }


    /**
     * <desc>
     * 将单个十六进制字符转换为字节
     * </desc>
     *
     * @param c 单个字符
     * @return 转换得到的byte
     * @author LewisLouis
     * @createDate 2017-11-10
     */
    private static byte toByte(char c) {
        byte b = (byte) "0123456789ABCDEF".indexOf(c);
        return b;
    }

    /**
     * <desc>
     * 把字节数组转换成16进制字符串.
     * </desc>
     *
     * @param bArray 待转换的byte数组
     * @return 转换得到的Hex字符串
     * @author LewisLouis
     * @createDate 2017-11-10
     */
    public static String bytesToHexStr(byte[] bArray) {
        if (bArray == null) {
            return "";
        }
        StringBuffer sb = new StringBuffer(bArray.length);
        String sTemp;
        for (int i = 0; i < bArray.length; i++) {
            sTemp = Integer.toHexString(0xFF & bArray[i]);
            if (sTemp.length() < 2)
                sb.append(0);
            sb.append(sTemp.toUpperCase());
        }
        return sb.toString();
    }

}
